from fastapi import APIRouter, Depends, HTTPException, status, WebSocket, WebSocketDisconnect
from sqlalchemy.orm import Session
from typing import List, Dict, Any, Optional

from app.db.database import get_db
from app.core.security import get_current_user
from app.schemas.chat import ChatBrief, Chat, Message, MessageCreate, PrivateChatCreate, GroupChatCreate
from app.crud import chat as chat_crud

router = APIRouter()

# 正常HTTP路由
@router.get("/", response_model=List[ChatBrief])
async def read_chats(
    skip: int = 0, 
    limit: int = 100,
    current_user: dict = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取用户的聊天列表"""
    chats = chat_crud.get_user_chats(db, user_id=current_user["id"], skip=skip, limit=limit)
    return chats

@router.post("/private", response_model=Chat)
async def create_private_chat(
    chat_create: PrivateChatCreate,
    current_user: dict = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """创建私聊会话"""
    chat, is_new = chat_crud.create_private_chat(db, user_id=current_user["id"], chat_create=chat_create)
    return chat

@router.post("/group", response_model=Chat)
async def create_group_chat(
    chat_create: GroupChatCreate,
    current_user: dict = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """创建群聊会话"""
    chat = chat_crud.create_group_chat(db, user_id=current_user["id"], chat_create=chat_create)
    return chat

@router.get("/{chat_id}", response_model=Chat)
async def read_chat(
    chat_id: int,
    current_user: dict = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取聊天会话详情"""
    # 检查聊天是否存在
    chat = chat_crud.get_chat(db, chat_id=chat_id)
    if not chat:
        raise HTTPException(status_code=404, detail="聊天不存在")
    
    # 检查用户是否是聊天参与者
    participant = chat_crud.get_chat_participant(db, chat_id=chat_id, user_id=current_user["id"])
    if not participant and chat.chat_type != "system":
        raise HTTPException(status_code=403, detail="您不是该聊天的参与者")
    
    return chat

@router.get("/{chat_id}/messages", response_model=List[Message])
async def read_messages(
    chat_id: int,
    skip: int = 0,
    limit: int = 50,
    current_user: dict = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取聊天消息列表"""
    # 检查聊天是否存在
    chat = chat_crud.get_chat(db, chat_id=chat_id)
    if not chat:
        raise HTTPException(status_code=404, detail="聊天不存在")
    
    # 检查用户是否是聊天参与者
    participant = chat_crud.get_chat_participant(db, chat_id=chat_id, user_id=current_user["id"])
    if not participant and chat.chat_type != "system":
        raise HTTPException(status_code=403, detail="您不是该聊天的参与者")
    
    messages = chat_crud.get_messages(db, chat_id=chat_id, skip=skip, limit=limit)
    return messages

@router.post("/{chat_id}/messages", response_model=Message)
async def create_message(
    chat_id: int,
    message: MessageCreate,
    current_user: dict = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """发送消息"""
    db_message = chat_crud.create_message(db, chat_id=chat_id, user_id=current_user["id"], message=message)
    if not db_message:
        raise HTTPException(status_code=404, detail="聊天不存在或您不是该聊天的参与者")
    
    return db_message

@router.post("/{chat_id}/read", response_model=dict)
async def mark_as_read(
    chat_id: int,
    message_id: Optional[int] = None,
    current_user: dict = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """标记消息为已读"""
    result = chat_crud.mark_messages_as_read(db, chat_id=chat_id, user_id=current_user["id"], message_id=message_id)
    if not result:
        raise HTTPException(status_code=404, detail="聊天不存在或您不是该聊天的参与者")
    
    return {"status": "success"}

@router.post("/{chat_id}/participants", response_model=dict)
async def add_participant(
    chat_id: int,
    user_id: int,
    is_admin: bool = False,
    current_user: dict = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """添加参与者到群聊"""
    # 检查当前用户是否是管理员
    current_participant = chat_crud.get_chat_participant(db, chat_id=chat_id, user_id=current_user["id"])
    if not current_participant or not current_participant.is_admin:
        raise HTTPException(status_code=403, detail="只有管理员可以添加参与者")
    
    participant = chat_crud.add_participant_to_chat(db, chat_id=chat_id, user_id=user_id, is_admin=is_admin)
    if not participant:
        raise HTTPException(status_code=404, detail="聊天不存在或不是群聊")
    
    return {"status": "success"}

@router.delete("/{chat_id}/participants/{user_id}", response_model=dict)
async def remove_participant(
    chat_id: int,
    user_id: int,
    current_user: dict = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """从群聊中移除参与者"""
    # 检查当前用户是否是管理员
    current_participant = chat_crud.get_chat_participant(db, chat_id=chat_id, user_id=current_user["id"])
    if not current_participant or not current_participant.is_admin:
        raise HTTPException(status_code=403, detail="只有管理员可以移除参与者")
    
    result = chat_crud.remove_participant_from_chat(db, chat_id=chat_id, user_id=user_id)
    if not result:
        raise HTTPException(status_code=404, detail="聊天不存在、不是群聊或用户不是参与者")
    
    return {"status": "success"}

# WebSocket连接管理器
class ConnectionManager:
    def __init__(self):
        # 格式: {user_id: {chat_id: websocket}}
        self.active_connections: Dict[int, Dict[int, WebSocket]] = {}
    
    async def connect(self, websocket: WebSocket, user_id: int, chat_id: int):
        await websocket.accept()
        if user_id not in self.active_connections:
            self.active_connections[user_id] = {}
        self.active_connections[user_id][chat_id] = websocket
    
    def disconnect(self, user_id: int, chat_id: int):
        if user_id in self.active_connections and chat_id in self.active_connections[user_id]:
            del self.active_connections[user_id][chat_id]
            if not self.active_connections[user_id]:
                del self.active_connections[user_id]
    
    async def send_personal_message(self, message: dict, user_id: int, chat_id: int):
        if user_id in self.active_connections and chat_id in self.active_connections[user_id]:
            websocket = self.active_connections[user_id][chat_id]
            await websocket.send_json(message)
    
    async def broadcast(self, message: dict, chat_id: int, exclude_user_id: int = None):
        for user_id, chats in self.active_connections.items():
            if user_id != exclude_user_id and chat_id in chats:
                await chats[chat_id].send_json(message)

manager = ConnectionManager()

@router.websocket("/ws/{chat_id}")
async def websocket_endpoint(
    websocket: WebSocket, 
    chat_id: int,
    token: str,
    db: Session = Depends(get_db)
):
    """WebSocket连接，用于实时聊天"""
    try:
        # 这里应该验证token并获取用户ID
        # 为简化，这里假设token是用户ID
        user_id = int(token)  # 实际应用中应该通过token验证用户身份
        
        # 检查用户是否是聊天参与者
        chat = chat_crud.get_chat(db, chat_id=chat_id)
        if not chat:
            await websocket.close(code=1000)
            return
            
        participant = chat_crud.get_chat_participant(db, chat_id=chat_id, user_id=user_id)
        if not participant and chat.chat_type != "system":
            await websocket.close(code=1000)
            return
        
        await manager.connect(websocket, user_id, chat_id)
        
        try:
            while True:
                # 接收消息
                data = await websocket.receive_json()
                
                # 创建消息
                message_create = MessageCreate(
                    content=data.get("content", ""),
                    content_type=data.get("content_type", "text"),
                    media_url=data.get("media_url")
                )
                
                # 保存消息到数据库
                db_message = chat_crud.create_message(db, chat_id=chat_id, user_id=user_id, message=message_create)
                
                if db_message:
                    # 转换消息为字典
                    message_dict = {
                        "id": db_message.id,
                        "chat_id": db_message.chat_id,
                        "sender_id": db_message.sender_id,
                        "content": db_message.content,
                        "content_type": db_message.content_type,
                        "media_url": db_message.media_url,
                        "is_read": db_message.is_read,
                        "created_at": db_message.created_at.isoformat()
                    }
                    
                    # 广播消息给其他聊天参与者
                    await manager.broadcast(message_dict, chat_id, exclude_user_id=user_id)
                    
                    # 发送消息给自己（确认）
                    await manager.send_personal_message(message_dict, user_id, chat_id)
                
        except WebSocketDisconnect:
            manager.disconnect(user_id, chat_id)
            
    except Exception as e:
        print(f"WebSocket error: {e}")
        await websocket.close(code=1000) 